/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.das.commonmodel.util;

import java.util.ArrayList;
import java.util.HashMap;

import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonModel;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.entity.GspCommonElement;
import com.inspur.edp.das.commonmodel.entity.GspCommonModel;
import com.inspur.edp.das.commonmodel.entity.GspCommonObject;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.util.DataValidator;

// import Inspur.Ecp.Caf.Common.*;

/**
 * CM扩展方法
 * 
 */
public final class CommonModelExtension {

//	private static String namespaceURI = "urn:schemas-microsoft-com:xml-msdata";
//	private static String prefix = "msdata";
//	private static String constraint = "Constraint1";

	/**
	 * 获取指定结点的属性字典，其中key 是LabelID
	 * 
	 * 包含非持久化属性和关联带出的属性
	 * 
	 * @param node
	 * @return
	 */
	@SuppressWarnings("unchecked")
	static HashMap<String, IGspCommonElement> getElements(IGspCommonObject node) {
		final String elementDicKey = "NodeElementDic";

		if (node == null || node.getContainElements() == null) {
			return null;
		}
		GspCommonObject co = (GspCommonObject) ((node instanceof GspCommonObject) ? node : null);
		if (co != null) {
			if (co.getExtProperties().containsKey(elementDicKey)) {
				// (java.util.HashMap<String, IGspCommonElement>)
				Object result = co.getExtProperties().get(elementDicKey);
				return (HashMap<String, IGspCommonElement>) result;
			}
		}

		HashMap<String, IGspCommonElement> rez = ((GspCommonObject) node).getAllElementDic();
		if (co != null) {
			co.getExtProperties().put(elementDicKey, rez);
		}
		return rez;
	}

	private static void getNodes(IGspCommonObject bizEntityObject, java.util.Map<String, IGspCommonObject> rez) {
		if (bizEntityObject.getContainChildObjects() == null) {
			return;
		}
		if (bizEntityObject.getContainChildObjects().size() == 0) {
			return;
		}
		// Java:
		for (IGspCommonObject obj : bizEntityObject.getContainChildObjects()) {
			getNodes(obj, rez);
			rez.put(obj.getCode(), obj);
		}
	}

	/**
	 * 递归取所有子Node
	 * 
	 * @param model
	 * @return 返回结果集为字典类型，不保证遍历顺序
	 */
	public static HashMap<String, IGspCommonObject> getNodes(IGspCommonModel model) {
		final String nodeDicKey = "ModelNodesDic";

		if (model == null || model.getMainObject() == null) {
			return null;
		}
		HashMap<String, IGspCommonObject> result = getExtProperty(model, nodeDicKey);
		if (result != null) {
			return result;
		}

		HashMap<String, IGspCommonObject> rez = new HashMap<String, IGspCommonObject>();
		getNodes(model.getMainObject(), rez);
		rez.put(model.getMainObject().getCode(), model.getMainObject());
		result = new HashMap<String, IGspCommonObject>(rez);
		setExtProperty(model, nodeDicKey, result);
		return result;
	}

	static boolean HasCodeNumberColumn(IGspCommonModel model) {
		DataValidator.checkForNullReference(model, "model");

		GspCommonModel cm = (GspCommonModel) ((model instanceof GspCommonModel) ? model : null);
		final String key = "HasCodeNumberColumn";
		if (cm != null && cm.getExtProperties().containsKey(key)) {
			return (boolean) cm.getExtProperties().get(key);
		}
		boolean result = false;
		for (IGspCommonField item : ((GspCommonObject) model.getMainObject()).getContainElements()) {
			GspCommonElement element = (GspCommonElement) item;
			if (element.getBillCodeConfig() != null && element.getBillCodeConfig().getCanBillCode()
					&& !element.getBillCodeConfig().getBillCodeID().isEmpty()) {
				result = true;
				break;
			}
		}
		if (cm != null) {
			cm.getExtProperties().put(key, result);
		}
		return result;
	}

	/**
	 * 按照层次遍历的BE结点列表
	 * 
	 * @return 结果集使用先根后子方式排序
	 */
	public static ArrayList<IGspCommonObject> getLevelOrderedNodes(IGspCommonModel model) {

		final String nodesListkey = "ModelLevelOrderedNodes";
		ArrayList<IGspCommonObject> nodes = getExtProperty(model, nodesListkey);
		if (nodes != null) {
			return nodes;
		}

		nodes = new ArrayList<IGspCommonObject>();
		java.util.LinkedList<IGspCommonObject> nodeQueue = new java.util.LinkedList<IGspCommonObject>();
		nodeQueue.offer(model.getMainObject());

		while (nodeQueue.size() > 0) {
			IGspCommonObject node = nodeQueue.poll();
			if (node == null) // TODO ERROR?
			{
				continue;
			}

			nodes.add(node);
			if (node.getContainChildObjects().size() <= 0) {
				continue;
			}

			for (IGspCommonObject child : node.getContainChildObjects()) {
				nodeQueue.offer(child);
			}
		}
		setExtProperty(model, nodesListkey, nodes);
		return nodes;
	}

	// region 私有方法
	// where T : class
	@SuppressWarnings("unchecked")
	private static <T> T getExtProperty(IGspCommonModel model, String key) {
		GspCommonModel cm = (GspCommonModel) ((model instanceof GspCommonModel) ? model : null);
		if (cm == null) {
			return null;
		}
		if (cm.getExtProperties().containsKey(key)) {
			return (T) cm.getExtProperties().get(key);
		}
		return null;
	}

	// where T : class
	private static <T> void setExtProperty(IGspCommonModel model, String key, T value) {
		GspCommonModel cm = (GspCommonModel) ((model instanceof GspCommonModel) ? model : null);
		if (cm == null) {
			return;
		}

		cm.getExtProperties().put(key, value);
	}

	// endregion
}
